// ----------------------------------------------------------------------------
// serialize_member.h
// ----------------------------------------------------------------------------
#pragma once
#include <stddef.h>
#include <fw/base/runtime/hash.h>
#include <fw/base/serialize/serialize_allocator.h>
#include <fw/base/serialize/serialize_status.h>

namespace fw
{
	class SerializeCompoundType;
	class SerializeType;
	class SerializeScalarValue;
	class SerializeSchema;
	class ByteReader;
	class ByteWriter;
	
	class SerializeMember
	{
	private:
		Hash							m_typename;
		size_t							m_offset;
		int								m_count;
		const SerializeType*			m_type;
		const SerializeCompoundType*	m_scope;
		
	protected:
		
		enum ByteCode
		{
			kByteCode_Instance,
			kByteCode_CountedPointer,
			kByteCode_StringPointer,
			kByteCode_Mask = 0x07,
		};
		
		enum ByteCodeFlag
		{
			kByteCodeFlag_Array		= 1 << 7, // メンバ変数はコンパウンド型の中に配列として存在している.
			kByteCodeFlag_CountName	= 1 << 6, // メンバ変数はひとつ以上のメンバを差すポインタ.
			kByteCodeFlag_TermName  = 1 << 5,
			kByteCodeFlag_TermValue = 1 << 4,
		};
		
	public:
				 SerializeMember(int count, Hash typeName);
		virtual ~SerializeMember();
		
		char*							GetDataPtr		(	   char* scopeData, int index) const;
		const char*						GetDataPtr		(const char* scopeData, int index) const;
		
		SerializeScalarValue			ReadScalarValue	(const char* scopeData) const;
		
		size_t							GetTotalSize	() const;
		SerializeStatus					FixUp			(SerializeSchema& schema, const SerializeMember* previousMember);
		
		virtual size_t					GetSize			() const = 0;
		virtual size_t					GetAlignment	() const = 0;
		virtual int						GetPointerCount	(const char* scopeData, int index) const = 0;
		virtual const SerializeType*	PreFixUp		(SerializeSchema& schema, Hash typeName) = 0;
		virtual void					Convert			(char*					dstData,
														 const char*			srcData,
														 const SerializeMember& srcMember,
														 SerializeAllocator&	alloc) const = 0;
		virtual void					Write			(ByteWriter& writer) const = 0;
		static SerializeMember*			ReadNew			(ByteReader& reader);
		virtual uint64_t				GetChecksum		(uint64_t basis) const;
		
		void							SetScope		(const SerializeCompoundType* cope);
		
		size_t							GetOffset() const
		{
			return m_offset;
		}
		
		int								GetCount() const
		{
			return m_count;
		}
		
		const SerializeType*			GetType() const
		{
			return m_type;
		}
		
		const SerializeCompoundType*	GetScope() const
		{
			return m_scope;
		}
		
		Hash							GetTypeName() const
		{
			return m_typename;
		}
		
	}; // class SerializeMember
	
	
} // namespace fw
